package cs294s.liveradar.data;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import org.json.simple.JSONObject;

import android.location.Location;
import android.util.Log;

import com.google.android.maps.GeoPoint;

import cs294s.liveradar.service.FeedManager;


public class Filter {
	
	String id;
	Set<String> tags  = new HashSet<String>();
	GeoPoint center;
	Double radius;
	String distanceUnits;
	ArrayList<Person> authors = new ArrayList<Person>();;
	Double timeRange;
	String timeUnits;
	String description;
	String name;
	
	public Filter() {
		addTag(FeedManager.LIVERADAR_TAG);
	}
	
	public Filter(JSONObject json) {
		this();
		setId((String)json.get("id"));
		addTags((String)json.get("tags"));
		setDescription((String)json.get("desc"));
		setName((String)json.get("name"));
		Double timeRange = (Double)json.get("timeRange");
		setTimeRange(timeRange);
		setTimeUnits((String)json.get("timeUnits"));
		setCenter(new GeoPoint(((Long)json.get("lat")).intValue(), ((Long)json.get("lon")).intValue()));
		setDistanceUnits((String)json.get("distanceUnits"));
		setRadius((Double)json.get("radius"));
		
	}
	
	public void setId(String id) {this.id = id; }
	
	public void addTag(String tag) { tags.add(tag); }

	public void removeTag(String tag) { tags.remove(tag); }

	public void setCenter(GeoPoint location) { this.center = location; }

	public void setTimeRange(Double timeRange) { this.timeRange = timeRange; }

	public void addAuthor(Person author) { authors.add(author); }
	public void removeAuthor(Person author) { authors.remove(author); }


	public void setDescription(String desc) { this.description = desc; }
	
	public void setName(String name) { this.name = name; }
	
	public void setTimeUnits(String units) { this.timeUnits = units; }
	
	public void setDistanceUnits(String units) { this.distanceUnits = units; }
	
	public void setRadius(Double radius) { this.radius = radius; }

	public void addTags(String tags) { 
		String[] tags_arr =  tags.split(",");
		for(String t : tags_arr) {
			addTag(t.trim());
		}
	}


	public String tagsToString() {
		String result = "";
		for(String s : tags) {
			result += s + ", ";
		}
		result = result.substring(0, result.length()-2);
		return result;
	}

	public String[] tagsToStringArr() {
		return (String[])tags.toArray(new String[tags.size()]);
	}

	@SuppressWarnings("unchecked")
	public JSONObject toJSON() {

		JSONObject j = new JSONObject();
		j.put("id", id);
		j.put("tags", tagsToString());
		j.put("desc", description);
		j.put("name", name);
		j.put("timeRange", timeRange);
		j.put("timeUnits", timeUnits);
		j.put("lat", center.getLatitudeE6());
		j.put("lon", center.getLongitudeE6());
		j.put("radius", radius);
		j.put("distanceUnits", distanceUnits);
		j.put("authors", authors.toString());
		
		return j;
	}
	
	public String toParams() {
		String params = "";
		params += "id=" + id;
		params += "&tags=" + tagsToString();
		params += "&desc=" + description; 
		params += "&name=" + name;
		params += "&timeRange=" + timeRange;
		params += "&timeUnits=" + timeUnits;
		params += "&lat=" + center.getLatitudeE6();
		params += "&lon=" + center.getLongitudeE6();
		params += "&radius=" + radius;
		params += "&distanceUnits=" + distanceUnits;
		params += "&authors=" + authors.toString();
		
		//Need to HTML encode
		return params;
	}

	public String getId() {return id;}
	
	public GeoPoint getCenter() { return center; }

	public Double getTimeRange() { return timeRange; }
	public String getTimeUnits() { return timeUnits; }

	public Double getRadius() { return radius; }
	public String getDistanceUnits() { return distanceUnits; }
	//public Person getAuthor() { return author;}

	public String getDescription() { return description;}
	public String getName() { return name;}
	
	
	//Returns true if Blip passes filter
	public boolean passFilter(Blip b) {
		
		//Distance filter
		float results[] = new float[3];
		Location.distanceBetween(center.getLatitudeE6()/(1E6), center.getLongitudeE6()/(1E6), b.getLocation().getLatitudeE6()/(1E6), b.getLocation().getLongitudeE6()/(1E6), results);
		float distance = results[0];
		
		//Reject is distance is too far.
		Log.d("RADAR", "DISTANCE COMPARE - DISTANCE: " + metersToFeet(distance) + " MAX RADIUS: " + (double) radiusToFeet());
		if(metersToFeet(distance) > (double) radiusToFeet()) return false;
		
		//Time filter
		Date now = new Date();
		Date blipDate = b.getEventTime();
		double timeDiff = millisToMinutes(now.getTime()) - millisToMinutes(blipDate.getTime());
		
		Log.d("RADAR", "TIME COMPARE - DIFF: " + timeDiff + " MAX RANGE: " + timeToMinutes());
		if(timeDiff > timeToMinutes()) return false;
		
		return true;
	}
	
	private double radiusToFeet() {
		if(distanceUnits.equals("Feet")) return radius;
		if(distanceUnits.equals("Yards")) return yardsToFeet(radius);
		else return milesToFeet(radius);
	}
	
	private double yardsToFeet(double yards) {
		return yards*3;
	}
	
	private double milesToFeet(double miles) {
		return miles*5280;
	}
	
	private double metersToFeet(double meters) {
		return meters*3.2808399;
	}
	
	private double timeToMinutes() {
		if(timeUnits.equals("Minutes")) return timeRange;
		if(timeUnits.equals("Hours")) return timeRange*60;
		if(timeUnits.equals("Days")) return timeRange*60*24;
		if(timeUnits.equals("Weeks")) return timeRange*60*24*7;
		if(timeUnits.equals("Months")) return timeRange*60*24*30;
		else return timeRange*60*24*365;
		
	}
	
	private double millisToMinutes(double millis) {
		return millis/(1000*60);
	}

}
